package botlab.compiler;

import botlab.command.BaseCommand;
import java.io.IOException;
import java.io.InputStream;

/**
 *
 * @author Quentin
 */
public class CommandCreator
{
    // this is a singleton
    private static final CommandCreator instance = new CommandCreator();
    // a compiler
    private final MyCompiler<BaseCommand> compiler = new MyCompiler<BaseCommand>(null);
    // for unique class names
    private static int classNameSuffix = 0;
    private String classBaseName = "UserCommand";
    // package name
    private static final String PACKAGE_NAME = "runtime";
    // the Java source template
    private String template;

    /**
     * Get the singleton instance
     * @return the unique instance of CommandCreator
     */
    public static CommandCreator getInstance()
    {
        return instance;
    }
    
    /**
     * Generate Java source for a BaseCommand class and fill the doCommand
     * methode with <var>expr</var>
     *
     * @param expr String representation of Java source code.
     * @return an instance of the BaseCommand generated
     */
    public BaseCommand newBaseCommand(final String expr) throws IOException, CompilationException
    {
        String className=classBaseName+"_"+String.valueOf(classNameSuffix);
//        classNameSuffix++;
        String code = fillTemplate(PACKAGE_NAME, className, expr);
        return compiler.compile(code, className+".java");
    }


    /**
     * Return the BaseCommand Java source, substituting the given package name,
     * class name, and expression
     *
     * @param packageName a valid Java package name
     * @param className a valid Java class name
     * @param expression String representation of Java source code.
     * @return source for the new class implementing BaseCommand interface
     * filled with expression
     * @throws IOException
     */
    private String fillTemplate(String packageName, String className, String expression)
            throws IOException
    {
        if (template == null)
        {
            template = readTemplate();
        }
        // simplest "template processor":
        String source = template.replace("$packageName", packageName).replace("$className", className).replace("$code", expression);
        return source;
    }

    /**
     * Read the BaseCommand source template
     *
     * @return a source template
     * @throws IOException
     */
    private String readTemplate() throws IOException
    {
        InputStream inputStream = CommandCreator.class.getResourceAsStream(classBaseName+".java.template");
        int size = inputStream.available();
        byte bytes[] = new byte[size];
        if (size != inputStream.read(bytes, 0, size))
        {
            throw new IOException();
        }
        return new String(bytes, "US-ASCII");
    }
}
